# -*- coding: utf-8 -*- 
import os.path
from threading import Thread
from wx._misc import DateTime
APP_DIR, _ = os.path.split(os.path.split(os.path.split(os.path.abspath(globals()[ '__file__' ]))[0])[0])
import sys
sys.path.append(APP_DIR)
print APP_DIR
from chart_view import GraphFrame
from generated_sources import LinuxAnalyser, AboutDialog, NewMonitoringWizard
import wx.grid
from linux_analyser.core.governor import GathererGovernor
from linux_analyser.utils.utils import *
from linux_analyser.utils.stoppable_thread import StoppableThread
import csv
from time import sleep

DATA_DIR = os.path.join(os.path.split(APP_DIR)[0], 'test_data')

class MyGridTable(wx.grid.PyGridTableBase):
    def __init__(self, data_path):
        wx.grid.PyGridTableBase.__init__(self)
        self.data = []
        self.row_labels = ['Nazwa pliku', 'Typ', 'Obiekt', 'Zasoby', 'Aktywny']
        logs = self.get_log_files_list(data_path)
        self.populate_model(logs)
        pass
    
    def get_log_files_list(self, data_path):
        result = []
        for root, _, files in os.walk(data_path):
            for name in files:       
                filepath = os.path.join(root, name)
                result.append((name, filepath))
        return result
    
    def populate_model(self, logs):
        for log_name, log_path in logs:
            with open(log_path, 'r') as f:
                metadata_line = f.readline()
                metadata = str(metadata_line).split(';')
                self.data.append([log_name] + metadata + ["Nie"])        
    
    def populate_monitoring_model(self, monitorings):
        for logFile in monitorings.keys():
            try:
                i = self.data.index(next(subl for subl in self.data if logFile in subl))
                self.data[i] = [logFile] + monitorings[logFile]
            except:
                self.data.append([logFile] + monitorings[logFile])
        
    def GetColLabelValue(self, row):
        return self.row_labels[row]
    
    def GetNumberRows(self):
        """Return the number of rows in the grid"""
        return len(self.data)

    def GetNumberCols(self):
        """Return the number of columns in the grid"""
        return 5

    def IsEmptyCell(self, row, col):
        """Return True if the cell is empty"""
        return False

    def GetTypeName(self, row, col):
        """Return the name of the data type of the value in the cell"""
        return None

    def GetValue(self, row, col):
        """Return the value of a cell"""
        if len(self.data) > row:
            if len(self.data[row]) > col:
                return self.data[row][col]

    def SetValue(self, row, col, value):
        """Set the value of a cell"""
        pass
    
    
    
#    def ResetView(self):
#                """Trim/extend the control's rows and update all values"""
#                self.getGrid().BeginBatch()
#                for current, new, delmsg, addmsg in [
#                        (self.currentRows, self.GetNumberRows(), wxGRIDTABLE_NOTIFY_ROWS_DELETED, wxGRIDTABLE_NOTIFY_ROWS_APPENDED),
#                        (self.currentColumns, self.GetNumberCols(), wxGRIDTABLE_NOTIFY_COLS_DELETED, wxGRIDTABLE_NOTIFY_COLS_APPENDED),
#                ]:
#                        if new < current:
#                                msg = wxGridTableMessage(
#                                        self,
#                                        delmsg,
#                                        new, # position
#                                        current - new,
#                                )
#                                self.getGrid().ProcessTableMessage(msg)
#                        elif new > current:
#                                msg = wxGridTableMessage(
#                                        self,
#                                        addmsg,
#                                        new - current
#                                )
#                                self.getGrid().ProcessTableMessage(msg)
#                self.UpdateValues()
#                self.getGrid().EndBatch()
#
#                 The scroll bars aren't resized (at least on windows)
#                 Jiggling the size of the window rescales the scrollbars
#                h, w = grid.GetSize()
#                grid.SetSize((h + 1, w))
#                grid.SetSize((h, w))
#                grid.ForceRefresh()
#
#    def UpdateValues(self):
#                """Update all displayed values"""
#                msg = wxGridTableMessage(self, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES)
#                self.getGrid().ProcessTableMessage(msg)

class MonitoringStarter(StoppableThread):

    def __init__(self, governorOptions, startDate, endDate):
        StoppableThread.__init__(self)
        self.governorOptions = governorOptions
        self.startDate = startDate
        self.endDate = endDate
        self.governor = None
        
    def run(self):
        print "Przygotowywanie monitoringu"
        if self.startDate < DateTime.Now():
            self.startDate = DateTime.Now()
        if self.endDate != None :    
            self.governorOptions["run_time"] = self.endDate.GetTicks() - self.startDate.GetTicks()
        
            print "Monitorowany okres to " + str(self.governorOptions["run_time"]) + "s"
            if self.governorOptions["run_time"] < 0 :
                print 'Data rozpoczecia musi byc mniejsza od daty zakonczenia'
                return
        else:
            self.governorOptions["run_time"] = None
            
        self.governor_options = dict(not_blank_items(self.governorOptions))
        self.governor = GathererGovernor(**self.governorOptions)
        sleepTime = self.startDate.GetTicks() - DateTime.Now().GetTicks()
        print "Monitoring rozpocznie sie za " + str(sleepTime) + "s"
        sleep(sleepTime)
        print "Starting monitoring"
        self.governor.start()
        
    
class CustomLinuxAnalyser(LinuxAnalyser):
    def __init__(self, parent):
        #self.table = [ ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']]
        LinuxAnalyser.__init__(self, parent)
        self.grid_table = MyGridTable(DATA_DIR)
        self.monitorings_grid.SetTable(self.grid_table, takeOwnership=False)
        self.monitorings = {}
        self.monitors = {}
        
    def on_info(self, event):
        dialog = AboutDialog(self)
        dialog.ShowModal()
        dialog.Destroy()
        
    def on_exit(self, event):
        self.Close(True)
    
    def on_stop(self, event):
        selectedRows = self.monitorings_grid.GetSelectedRows()
        if len(selectedRows) == 0:
            return 
        for selectedRow in selectedRows :
            fileName = self.grid_table.GetValue(selectedRow, 0)
            self.grid_table.data[selectedRow][4] = 'Nie'
            print "Stopping monitoring to file " + fileName
            self.monitorings_grid.SetTable(self.grid_table, takeOwnership=False)
            monitor = self.monitors[fileName]
            if not monitor is None :
                print 'Stopping monitor starter'
                monitor.stop()
                governor = monitor.governor
                if not governor is None :
                    print 'Stopping governor'
                    governor.stop()
        
    def on_open(self, e):
        """ Open a file"""
        self.dirname = ''
        dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetFilename()
            self.dirname = dlg.GetDirectory()
            f = open(os.path.join(self.dirname, self.filename), 'r')
            fileContent = f.read()
#            self.control.SetValue(fileContent)
#            f.close()
            resources = ''
            if 'CPU' in fileContent:
                resources = 'Procesor '
            else :
                resources = resources + 'RAM'
            filename = self.dirname + '/' + self.filename
            self.monitorings[filename] = ['Procesy', '', resources, 'Nie']
            self.grid_table.populate_monitoring_model(self.monitorings)
            self.monitorings_grid.SetTable(self.grid_table, takeOwnership=False)
        dlg.Destroy()
        
    def on_new(self, event):
        wizard = NewMonitoringWizard(self)
        wizard.RunWizard(wizard.m_pages[0])
        self.initializeGatheres(wizard)
        
    def show_chart(self, event):
        #self.grid_table.rows = self.grid_table.rows + 1
        #self.monitorings_grid.GetTable().rows =  self.monitorings_grid.GetTable().rows + 1
        #self.grid_table.ResetView()
        #self.monitorings_grid.SetTable(self.grid_table, takeOwnership=False)
        #self.monitorings_grid.Update()
        #self.monitorings_grid.ForceRefresh()
        #self.m_scrolledWindow1.Refresh()
        #pass
        #dlg = wx.MessageDialog( self, "Selected row " + str(selectedRow), "Test", wx.OK)
        #dlg.ShowModal() # Show it
        #dlg.Destroy() # finally destroy it when finished.
        selectedRows = self.monitorings_grid.GetSelectedRows()
        if len(selectedRows) == 0:
            return
        for selectedRow in selectedRows :
            fileName = self.grid_table.GetValue(selectedRow, 0)
            if not os.path.isabs(fileName) :
                fileName = os.path.join(DATA_DIR, fileName)
            try:
                graph = GraphFrame(None, fileName)
                graph.Show(True)
            except:
                print 'Log file opening problem. Path - ' + fileName
                
    def initializeGatheres(self, wizard):
        processName = "*"
        cpu_username = "*"
        if wizard.monitorProcessWithName.GetValue(): #proces o nazwie
            processName = wizard.processName.GetValue()
        elif wizard.monitorProcessOfUser.GetValue(): #proces uzytkownika
            cpu_username = wizard.processOwner.GetValue()
          
        cpu = wizard.cpuUsage.GetValue()
        cpu_interval = wizard.cpuMonitoringInterval.GetValue()
        cpu_threshold = wizard.cpuThreshold.GetValue()
        
        ram = wizard.ramUsage.GetValue()
        ram_interval = wizard.ramMonitoringInterval.GetValue()
        ram_threshold = wizard.ramThreshold.GetValue()
        run_time = 10

        startDate = wizard.startDate.GetDate()
        startHour = wizard.startHour.GetValue(as_wxDateTime=True)
        
        startDate.SetHour(startHour.GetHour())
        startDate.SetMinute(startHour.GetMinute())
        startDate.SetSecond(startHour.GetSecond())
        
        endDate = wizard.stopDate.GetDate()
        endHour = wizard.stopHour.GetValue(as_wxDateTime=True)
        
        endDate.SetHour(endHour.GetHour())
        endDate.SetMinute(endHour.GetMinute())
        endDate.SetSecond(endHour.GetSecond())
        
        filepath = str(wizard.logFilePicker.GetPath())
        if filepath == None or len(filepath) == 0:
            return
        
        if not os.path.exists(filepath):
            open(filepath, 'w').close() 

        governor_options = {"cpu": cpu, "cpu_interval": cpu_interval, "cpu_threshold": cpu_threshold, "cpu_username": cpu_username,
                            "cpu_name": processName, "ram": ram, "ram_interval": ram_interval, "ram_threshold": ram_threshold,
                            "ram_username": cpu_username, "ram_name": processName, "run_time": run_time, "filename": filepath }     
        
        resources = ''
        if cpu :
            resources = 'Procesor '
        if ram :
            resources = resources + 'RAM'

        filename = os.path.basename(filepath)
            
        self.monitorings[filename] = ["Procesy", processName, resources, 'Tak']
        self.grid_table.populate_monitoring_model(self.monitorings)
        self.monitorings_grid.SetTable(self.grid_table, takeOwnership=False)
        
        if wizard.userStop.GetValue():
            endDate = None
            
        monitoringStarter  = MonitoringStarter(governor_options, startDate, endDate)
        self.monitors[filename]= monitoringStarter
        monitoringStarter.start()
        
app = wx.App(False)  # Create a new app, don't redirect stdout/stderr to a window.
frame = CustomLinuxAnalyser(None) # A Frame is a top-level window.
frame.Show(True)     # Show the frame.
app.MainLoop()
